// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.chimi.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.BarPointBusinessEnum;
import com.liuxinlong.enums.BarPointSourceEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.chimi.service.BarPointsService;
import com.liuxinlong.modules.chimi.service.BarPresentFlowService;
import com.liuxinlong.modules.dao.BarLuckAwardDao;
import com.liuxinlong.modules.dao.BarLuckDao;
import com.liuxinlong.modules.dao.BarLuckFlowDao;
import com.liuxinlong.modules.dao.BarPointsFlowDao;
import com.liuxinlong.modules.dao.BarPresentDao;
import com.liuxinlong.modules.dao.BarPresentFlowDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.entity.BarLuck;
import com.liuxinlong.modules.entity.BarLuckAward;
import com.liuxinlong.modules.entity.BarLuckFlow;
import com.liuxinlong.modules.entity.BarPointsFlow;
import com.liuxinlong.modules.entity.BarPresent;
import com.liuxinlong.modules.entity.BarPresentFlow;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 论坛礼品流水服务层接口实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022-07-28
 */
@Service
@Slf4j
public class BarPresentFlowServiceImpl implements BarPresentFlowService {

    @Autowired
    private BarPresentFlowDao barPresentFlowDao;

    @Autowired
    private BarPresentDao barPresentDao;

    @Autowired
    private BarLuckDao barLuckDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private BarPointsFlowDao barPointsFlowDao;

    @Autowired
    private BarPointsService barPointsService;

    @Autowired
    private BarLuckAwardDao barLuckAwardDao;

    @Autowired
    private BarLuckFlowDao barLuckFlowDao;

    @Override
    public List<Map<String, Object>> pagePresentFlow(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<BarPresentFlow> originalList = barPresentFlowDao.pageBarPresentFlowList(queryParam);
        return completeResult(originalList, startNum);
    }

    @Override
    public int getPresentFlowCount(Map<String, Object> queryParam) {
        return barPresentFlowDao.getBarPresentFlowCount(queryParam);
    }

    @Override
    public void addPresentFlow(BarPresentFlow barPresentFlow) {
        BarLuck barLuck = barLuckDao.selectById(barPresentFlow.getLuckId());
        if (ObjectUtils.isEmpty(barLuck)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，活动信息不存在！");
        }
        BarPresent barPresent = barPresentDao.selectById(barPresentFlow.getPresentId());
        if (ObjectUtils.isEmpty(barPresent)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，礼品信息不存在！");
        }
        BarLuckAward barLuckAward = barLuckAwardDao.getLuckPresent(barLuck.getId(),barPresent.getId());
        if (ObjectUtils.isEmpty(barLuckAward)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，奖品信息不存在！");
        }
        if (barLuckAward.getLeftNum() < 1) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，奖品剩余数量不足！");
        }
        User user = userDao.selectById(barPresentFlow.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，用户信息不存在！");
        }
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        if (barLuck.getType() == 0) {
            if (barLuck.getJoinType() == 1) {
                BarPointsFlow pointsFlow = new BarPointsFlow();
                pointsFlow.setId(SnowFlake.nextIdStr());
                pointsFlow.setUserId(barPresentFlow.getUserId());
                pointsFlow.setPoints(barLuck.getJoinThreshold());
                pointsFlow.setOperateTime(currentTime);
                pointsFlow.setType(2);
                pointsFlow.setSourceType(BarPointSourceEnum.CONSUMPTION.getValue());
                barPointsFlowDao.insert(pointsFlow);
            }
            if (barPresent.getType() == 2) {
                barPointsService.updateUserPoints(user.getId(), BarPointBusinessEnum.LUCK_GIFT.getValue(),barPresent.getPointNum());
            }
        } else {
            int needPoint = barPresent.getNeedPoint();
            BarPointsFlow pointsFlow = new BarPointsFlow();
            pointsFlow.setId(SnowFlake.nextIdStr());
            pointsFlow.setUserId(barPresentFlow.getUserId());
            pointsFlow.setPoints(needPoint);
            pointsFlow.setOperateTime(currentTime);
            pointsFlow.setType(2);
            pointsFlow.setSourceType(BarPointSourceEnum.CONSUMPTION.getValue());
            barPointsFlowDao.insert(pointsFlow);
        }
        barLuckAward.setLeftNum(barLuckAward.getLeftNum() - 1);
        barLuckAwardDao.updateById(barLuckAward);
        barPresentFlow.setId(SnowFlake.nextIdStr());
        barPresentFlowDao.insert(barPresentFlow);
        BarLuckFlow barLuckFlow = new BarLuckFlow();
        barLuckFlow.setLuckId(barLuck.getId());
        barLuckFlow.setHit(1);
        barLuckFlow.setOperateTime(currentTime);
        barLuckFlow.setUserId(user.getId());
        barLuckFlow.setUserName(user.getName());
        barLuckFlow.setId(SnowFlake.nextIdStr());
        barLuckFlowDao.insert(barLuckFlow);
    }

    @Override
    public void updatePresentFlow(BarPresentFlow barPresentFlow) {
        String id = barPresentFlow.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改礼品流水信息异常，礼品流水不存在！");
        }
        BarPresentFlow oldInfo = barPresentFlowDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改礼品流水信息异常，礼品流水不存在！");
        }
        barPresentFlowDao.updateById(barPresentFlow);
    }

    @Override
    public void deletePresentFlow(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除礼品流水信息异常，礼品流水不存在！");
        }
        BarPresentFlow oldInfo = barPresentFlowDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除礼品流水信息异常，礼品流水不存在！");
        }
        barPresentFlowDao.deleteById(id);
    }

    @Override
    public void updatePresentFlowStatus(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改礼品发放状态异常，礼品流水不存在！");
        }
        BarPresentFlow oldInfo = barPresentFlowDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改礼品发放状态异常，礼品流水不存在！");
        }
        int targetStatus = oldInfo.getStatus() == 0 ? 1 : 0;
        barPresentFlowDao.updatePresentFlowStatus(id, targetStatus);
    }

    @Override
    public void exportPresentFlow(String id, HttpServletResponse response) {
        Map<String, Map<String, String>> presentMap = barPresentDao.queryPresentMap();
        Map<String, Map<String, String>> luckMap = barLuckDao.queryLuckMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        ExcelData data = new ExcelData();
        data.setFileName("中奖记录导出excel.xlsx");
        Map<String,Object> queryParam=new HashMap<>();
        queryParam.put("startNum",0);
        queryParam.put("pageSize",10000);
        queryParam.put("luckId",id);
        List<BarPresentFlow> originalList = barPresentFlowDao.pageBarPresentFlowList(queryParam);
        String[] head = {"序号","活动名称", "礼品名称", "用户名称", "状态", "中奖时间"};
        data.setHead(head);
        String[][] dataList = new String[originalList.size()][head.length];
        int index = 0;
        for (BarPresentFlow item : originalList) {
            dataList[index][0] = String.valueOf(index+1);
            dataList[index][1] = presentMap.containsKey(item.getPresentId()) ? presentMap.get(item.getPresentId()).get("name") : "";
            dataList[index][2] = luckMap.containsKey(item.getLuckId()) ? luckMap.get(item.getLuckId()).get("title") : "";
            dataList[index][3] = userMap.containsKey(item.getUserId()) ? userMap.get(item.getUserId()).get("name") : "";
            dataList[index][4] = item.getStatus() == 1 ? "已发放" : "未发放";
            dataList[index][5] = item.getOperateTime();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    /**
     * 数据补全转换
     *
     * @param originList 原始数据列表
     * @param startNum   起始查询数
     * @return 补全数据
     */
    private List<Map<String, Object>> completeResult(List<BarPresentFlow> originList, int startNum) {
        if (ObjectUtils.isEmpty(originList)) {
            return new ArrayList<>();
        }
        Map<String, Map<String, String>> presentMap = barPresentDao.queryPresentMap();
        Map<String, Map<String, String>> luckMap = barLuckDao.queryLuckMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        int sort = startNum + 1;
        for (BarPresentFlow record : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(record);
            map.put("sort", sort);
            map.put("name", presentMap.containsKey(record.getPresentId()) ? presentMap.get(record.getPresentId()).get("name") : "");
            map.put("luckName", luckMap.containsKey(record.getLuckId()) ? luckMap.get(record.getLuckId()).get("title") : "");
            map.put("userName", userMap.containsKey(record.getUserId()) ? userMap.get(record.getUserId()).get("name") : "");
            resultList.add(map);
            sort++;
        }
        return resultList;
    }
}
